<template>
  <div class="quill-editor">
    <slot name="toolbar"></slot>
    <div ref="refQuillEditor"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, computed, onMounted, onBeforeUnmount } from 'vue'
import _Quill from 'quill'
import defaultOptions from './options'

interface Props {
  content?: string
  disabled?: boolean
  options?: any
  globalOptions?: any
}

const Quill = window.Quill || _Quill
const props = withDefaults(defineProps<Props>(), {
  disabled: false,
  options: {},
  globalOptions: {},
})
const model = defineModel()
const emit = defineEmits(['image-choose', 'input', 'change', 'ready', 'blur', 'focus'])

let quill : any = null
const refQuillEditor = ref()
const content = ref('')

const changed = (newVal : any, oldVal : any) => {
  if (quill) {
    if (newVal && newVal !== content.value) {
      quill.clipboard.dangerouslyPasteHTML(newVal)
      quill.focus()
      content.value = newVal
    } else if (!newVal) {
      quill.setText('')
    }
  }
}

watch(computed(() => props.content), changed)
watch(computed(() => model.value), changed)
watch(computed(() => content.value), changed)
watch(computed(() => props.disabled), (newVal : boolean, oldVal : boolean) => {
  if (quill) {
    quill.enable(!newVal)
  }
})

onMounted(() => {
  const options = {...defaultOptions, ...props.globalOptions, ...props.options}
  quill = new Quill(refQuillEditor.value, options)
  quill.enable(false)

  if (model.value || props.content) {
    quill.clipboard.dangerouslyPasteHTML(model.value || props.content)
  }
  if (!props.disabled) {
    quill.enable(true)
  }

  const toolbar : any = quill.getModule('toolbar')
  toolbar.addHandler('image', () => emit('image-choose'))

  quill.on('selection-change', (range : boolean) => {
    if (!range) {
      emit('blur', quill)
    } else {
      emit('focus', quill)
    }
  })

  quill.on('text-change', (delta, oldContents, source) => {
    const text = quill.getText()
    const html = refQuillEditor.value.children[0].innerHTML
    content.value = html
    model.value = html
    emit('input', html)
    emit('change', { html, text, quill })
  })

  emit('ready', quill)
})

onBeforeUnmount(() => {
  quill = null
})
</script>